package com.sc.nft.controller;

import java.util.List;
import java.util.concurrent.TimeUnit;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.sc.nft.annotation.UserLogin;
import com.sc.nft.controller.request.IdRequest;
import com.sc.nft.controller.request.draw.MallAcceptPrizeRequest;
import com.sc.nft.controller.request.draw.MallDrawPrizePoolRequest;
import com.sc.nft.controller.request.draw.MallDrawPrizeRequest;
import com.sc.nft.controller.request.draw.MallUserDrawRecordDetailRequest;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.vo.draw.MallDrawActivityVO;
import com.sc.nft.entity.vo.draw.MallDrawPrizeNoticeVO;
import com.sc.nft.entity.vo.draw.MallDrawPrizePoolVO;
import com.sc.nft.entity.vo.draw.MallDrawPrizeResultVO;
import com.sc.nft.entity.vo.draw.MallUserDrawRecodVO;
import com.sc.nft.entity.vo.draw.MallUserDrawRecordDetailVO;
import com.sc.nft.entity.vo.draw.MallUserPrizeVO;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.MallDrawRecordService;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;

import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

@RestController
@Slf4j
@RequestMapping("/mall/drawActivity")
@Api(tags = "商城抽奖")
public class MallDrawActivityController {

    @Autowired
    private MallDrawRecordService mallDrawRecordService;

    @Autowired
    private RedissonClient redissonClient;

    private Long getUserId() {
        UserInfo userInfo = UserPool.getUser();
        return userInfo.getId();
    }

    @PostMapping(value = "/listDrawActivity", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "分页获取抽奖活动列表", notes = "获取抽奖活动信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SneakyThrows
    public PageResult<MallDrawActivityVO> listDrawActivity(@RequestBody PageRequest pageRequest) {
        return PageResult.success(mallDrawRecordService.listDrawActivity(pageRequest));
    }

    @PostMapping(value = "/getDrawActivity", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取抽奖活动信息", notes = "获取抽奖活动信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @SneakyThrows
    public Result<MallDrawActivityVO> getDrawActivity(@Validated @RequestBody IdRequest idRequest) {
        return Result.success(mallDrawRecordService.getDrawActivity(getUserId(), idRequest.getId()));
    }

    @PostMapping(value = "/getDrawPrizePool", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取奖池信息", notes = "获取奖池信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @SneakyThrows
    public Result<MallDrawPrizePoolVO> getDrawPrizePool(
        @Validated @RequestBody MallDrawPrizePoolRequest drawPrizePoolRequest) {
        return Result.success(mallDrawRecordService.getPrizePool(getUserId(), drawPrizePoolRequest.getPrizePoolId(),
            drawPrizePoolRequest.getActivityId()));
    }

    @PostMapping(value = "/drawPrize", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "抽奖", notes = "抽奖", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @SneakyThrows
    public Result<MallDrawPrizeResultVO> drawPrize(@Validated @RequestBody MallDrawPrizeRequest drawPrizeRequest) {
        UserInfo userInfo = UserPool.getUser();
        String lockKey = StrUtil.format("mall_draw_prize:{}", drawPrizeRequest.getPrizePoolId());
        RLock lock = redissonClient.getLock(lockKey);
        if (!lock.tryLock(5, TimeUnit.SECONDS)) {
            throw new GlobalRunTimeException("系统繁忙请稍后再试~");
        }
        MallDrawPrizeResultVO result = null;
        try {
            result = mallDrawRecordService.drawPrize(userInfo, drawPrizeRequest.getPrizePoolId(),
                drawPrizeRequest.getActivityId());
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
        return Result.success(result);
    }

    @PostMapping(value = "/acceptPrize", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "领取奖品", notes = "领取奖品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @SneakyThrows
    public Result<Boolean> acceptPrize(@Validated @RequestBody MallAcceptPrizeRequest acceptPrizeRequest) {
        Long userId = getUserId();
        String lockKey = StrUtil.format("mall_accept_prize:{}", userId);
        RLock lock = redissonClient.getLock(lockKey);
        if (!lock.tryLock(5, TimeUnit.SECONDS)) {
            throw new GlobalRunTimeException("系统繁忙请稍后再试~");
        }
        Boolean result = Boolean.FALSE;
        try {
            result = mallDrawRecordService.acceptPrize(userId, acceptPrizeRequest.getActivityId());
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
        return Result.success(result);
    }

    @PostMapping(value = "/getUserPrizePool", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取用户奖池信息，传活动id", notes = "获取用户奖池信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @SneakyThrows
    public Result<MallUserPrizeVO> getUserPrizePool(@Validated @RequestBody IdRequest idRequest) {
        return Result.success(mallDrawRecordService.getUserPrizePool(getUserId(), idRequest.getId()));
    }

    @PostMapping(value = "/getUserDrawRecordList", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取用户抽奖记录", notes = "获取用户奖池信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @SneakyThrows
    public PageResult<MallUserDrawRecodVO> getUserPrizeRecordList(@RequestBody PageRequest pageRequest) {
        return PageResult.success(mallDrawRecordService.listUserPrizeRecord(getUserId(), pageRequest));
    }

    @PostMapping(value = "/getUserDrawRecordDetail", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "用户抽奖记录详细信息", notes = "获取记录详细信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @SneakyThrows
    public Result<List<MallUserDrawRecordDetailVO>> getUserDrawRecordDetail(
        @RequestBody MallUserDrawRecordDetailRequest detailRequest) {
        return Result.success(mallDrawRecordService.getUserDrawRecordDetail(getUserId(), detailRequest.getActivityId(),
            detailRequest.getId()));
    }

    @PostMapping(value = "/getDrawNotice", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取用户抽奖提示，前端每隔5s~10s调用一次", notes = "获取用户抽奖提示", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SneakyThrows
    public Result<List<MallDrawPrizeNoticeVO>> getDrawNotice(@Validated @RequestBody IdRequest idRequest) {
        return Result.success(mallDrawRecordService.getDrawNotice(idRequest.getId()));
    }

}
